﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using MovieRental.Entities;
using MovieRental.SqlRepositoryLibrary.Converters;
using MovieRental.DataInterfaces;
using System.Data.SqlClient;
using MovieRental.GeneralDataExceptions;

namespace MovieRental.SqlRepositoryLibrary
{
    public class SqlLoanCartRepository : SqlRepository<LoanCartInfo, Guid, LoanCartConverter>, ILoanCartRepository
    {
        protected SqlLoanRepository _loanRepository;

        public SqlLoanCartRepository(string connectionString)
            : base(connectionString)
        {
            _loanRepository = new SqlLoanRepository(connectionString);
        }

        protected override bool Contains(LoanCartInfo entity)
        {
            return Contains(entity.Id);
        }

        public override void Delete(LoanCartInfo entity)
        {
            Delete(entity.Id);
        }

        public override void Save(LoanCartInfo entity)
        {
            if (Contains(entity))
            {
                var oldCart = Load(entity.Id);
                _loanRepository.Delete(entity.Loans.First().LoanCartId);
            }
            base.Save(entity);
            foreach (var loan in entity.Loans)
                _loanRepository.Save(loan);
        }

        public override void Delete(Guid id)
        {
            _loanRepository.Delete(id);
            base.Delete(id);
        }

        public override LoanCartInfo Load(Guid id)
        {
            var cart = base.Load(id);
            foreach (var loan in _loanRepository.LoadAllForCart(id))
                cart.Loans.Add(loan);
            return cart;
        }

        private IEnumerable<LoanCartInfo> LoadLoans(IEnumerable<LoanCartInfo> carts)
        {
            var list = carts.ToList();
            for (int i = 0; i < list.Count(); i++)
                foreach (var loan in _loanRepository.LoadAllForCart(list[i].Id))
                    list[i].Loans.Add(loan);
            return list;
        }

        public override IEnumerable<LoanCartInfo> LoadAll()
        {
            var carts = new List<LoanCartInfo>(base.LoadAll());
            return LoadLoans(carts);
        }

        public IEnumerable<LoanCartInfo> LoadAllForDay(DateTime date)
        {
            using (var connection = ProvideConnection())
            {
                SqlCommand command = new SqlCommand();
                var mapping = (Converter as LoanCartConverter).Mapping;
                command.CommandText = string.Format("SELECT * FROM {0} WHERE DATEDIFF(day, {1}, {2})=0", mapping.TableName, mapping["LoanDate"].Name, "@LoanDate");
                command.Parameters.Add("@LoanDate", System.Data.SqlDbType.DateTime);
                command.Parameters["@LoanDate"].Value = date;
                command.Connection = connection;
                try
                {
                    return LoadLoans(GetEnumerableFromReaderCommand(command));
                }
                catch (Exception ex)
                {
                    throw new DbConnectionException("Can't connect to the db.", ex);
                }
            }
        }

        public IEnumerable<LoanCartInfo> LoadAllForCustomer(Guid customerId)
        {
            using (var connection = ProvideConnection())
            {
                SqlCommand command = new SqlCommand();
                var mapping = (Converter as LoanCartConverter).Mapping;
                command.CommandText = string.Format("SELECT * FROM {0} WHERE {1}={2}", mapping.TableName, mapping["CustomerId"].Name, "@CustomerId");
                command.Parameters.Add("@CustomerId", System.Data.SqlDbType.UniqueIdentifier);
                command.Parameters["@CustomerId"].Value = customerId;
                command.Connection = connection;
                try
                {
                    return LoadLoans(GetEnumerableFromReaderCommand(command));
                }
                catch (Exception ex)
                {
                    throw new DbConnectionException("Can't connect to the db.", ex);
                }
            }
        }
    }
}
